package com.suse.common.util.extra;

import cn.hutool.core.util.ObjectUtil;
import com.suse.common.util.core.StringUtil;
import com.suse.common.util.io.IoUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.CharUtils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 脱敏工具类
 * </p>
 *
 * @author 辜玉彬
 * @since 2022-08-31 13:40
 */
@Slf4j
public class DesensitizationUtil {

    // 替换符
    private static final String REPLACEMENT = "***";

    // 根节点
    private static final TreeNode rootNode = new TreeNode();

    static {
        InputStream in = null;
        BufferedReader bufferedReader = null;
        try {
            in = DesensitizationUtil.class.getClassLoader().getResourceAsStream("sensitive-words.txt");
            bufferedReader = new BufferedReader(new InputStreamReader(in));
            String keyword;
            while ((keyword = bufferedReader.readLine()) != null) {
                addKeyword(keyword);
            }
        } catch (Exception e) {
            log.error("加载敏感词文件失败:" + e.getMessage());
        }finally {
            IoUtil.close(in,bufferedReader);
        }
    }

    /**
     * 脱敏
     * @param text 需要脱敏的文本
     * @return 脱敏后的文本
     */
    public static String desensitize(String text) {
        if (StringUtil.isEmpty(text)) {
            return null;
        }

        // 指针1
        TreeNode tempNode = rootNode;
        // 指针2
        int h = 0;
        // 指针3
        int f = 0;
        // 结果
        StringBuilder sb = new StringBuilder();

        while (f < text.length()) {
            char c = text.charAt(f);
            if (isSymbol(c)) {
                if (tempNode == rootNode) {
                    sb.append(c);
                    h++;
                }
                f++;
                continue;
            }
            // 检查下级结点
            tempNode = tempNode.getSubNode(c);
            if (ObjectUtil.isNull(tempNode)) {
                sb.append(text.charAt(h));
                f = ++h;
                tempNode = rootNode;
            }else if (tempNode.isKeywordEnd()) {
                sb.append(REPLACEMENT);
                h = ++f;
                tempNode = rootNode;
            }else {
                f++;
            }
        }

        sb.append(text.substring(h));

        return sb.toString();

    }

    private static boolean isSymbol(char c) {
        return CharUtils.isAsciiAlphanumeric(c);
    }

    /**
     * 将敏感词添加到前缀树中
     * @param keyword 敏感词
     */
    private static void addKeyword(String keyword) {
        TreeNode tempNode = rootNode;
        for (int i = 0;i < keyword.length();i++) {
            char c = keyword.charAt(i);
            TreeNode subNode = tempNode.getSubNode(c);
            if (ObjectUtil.isNull(subNode)) {
                // 初始化子节点
                subNode = new TreeNode();
                tempNode.addSubNode(c,subNode);
            }
            // 指向子节点，进入下一轮循环
            tempNode = subNode;
            // 设置结束标志
            if (i == keyword.length() - 1) {
                tempNode.setKeywordEnd(true);
            }
        }
    }

    @Data
    private static class TreeNode {

        private boolean keywordEnd = false;

        private final Map<Character, TreeNode> subNodes = new HashMap<>();

        public void addSubNode(Character c,TreeNode node) {
            subNodes.put(c,node);
        }

        public TreeNode getSubNode(Character c) {
            return subNodes.get(c);
        }

    }

}
